﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MainWindow.xaml.cs" company="arvystate.net">
//   arvystate.net 
// </copyright>
// <summary>
//   Interaction logic for MainWindow.xaml
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace PresentationAid
{
    using System;
    using System.AutoUpdate.Core;
    using System.AutoUpdate.Managers;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls.Primitives;
    using System.Windows.Resources;
    using System.Windows.Threading;

    using Kinect.Toolbox;

    using Microsoft.Kinect;

    using NLog;
    using NLog.Config;
    using NLog.Targets.Wrappers;

    using PresentationAid.Control;
    using PresentationAid.Core;
    using PresentationAid.Dialog;
    using PresentationAid.Lib.Enums;
    using PresentationAid.Lib.GestureEngines;
    using PresentationAid.Lib.Gestures;
    using PresentationAid.Lib.Helpers;
    using PresentationAid.Settings;

    /// <summary>
    /// Interaction logic for MainWindow
    /// </summary>
    public partial class MainWindow
    {
        #region Static Fields

        /// <summary>
        /// The logger.
        /// </summary>
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        #endregion

        #region Fields

        /// <summary>
        /// The _dispatcher timer.
        /// </summary>
        private readonly DispatcherTimer dispatcherTimer;

        // Additional windows

        /// <summary>
        /// The _gesture dialog.
        /// </summary>
        private readonly GestureTest gestureDialog;

        /// <summary>
        /// The _overlay window.
        /// </summary>
        private readonly OverlayWindow overlayWindow;

        /// <summary>
        /// The _application icon type.
        /// </summary>
        private ApplicationIconType applicationIconType;

        // Holds variable if it should move to tray when it is ready

        /// <summary>
        /// The _has moved to tray.
        /// </summary>
        private bool hasMovedToTray;

        // Keep record of those who are not tracked in controllable environment

        /// <summary>
        /// The _not tracked first gesture.
        /// </summary>
        private DateTime notTrackedFirstGesture;

        /// <summary>
        /// The _not tracked notice count.
        /// </summary>
        private int notTrackedNoticeCount;

        /// <summary>
        /// The _skeletons.
        /// </summary>
        private Skeleton[] skeletons;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindow"/> class.
        /// </summary>
        public MainWindow()
        {
            Logger.Trace("Init: MainWindow");

            // Overlay window
            this.overlayWindow = new OverlayWindow();
            this.gestureDialog = new GestureTest();

            this.applicationIconType = ApplicationIconType.None;

            this.InitializeComponent();

            // Debug mode
            this.ToggleDebugMode(SettingManager.Instance.DebugMode);

            this.Update(this, new EventArgs());

            Logger.Trace("InitDetail: MainWindow - StartDispatcherTimer: {0}", 200);

            this.dispatcherTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };

            this.dispatcherTimer.Tick += this.Update;
            this.dispatcherTimer.Start();

            // Auto Update events
            UpdateManager.Instance.UpdateCheckFinished += this.OnUpdateCheckFinished;

            // Load Kinect now...
            KinectSensorManager.Instance.GestureRecognized += this.OnGestureRecognized;
            KinectSensorManager.Instance.SkeletonFrameReady += this.OnSkeletonFrameReady;

            KinectSensorManager.Instance.InitializeDefaultSensor();

            if (KinectSensorManager.Instance.IsInitialized)
            {
                Logger.Debug(
                    "Init: MainWindow - SensorInitialized, Sensor: {0}", KinectSensorManager.Instance.KinectSensor);
                KinectSensorManager.Instance.StartKinect();
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Changes application tray icon
        /// </summary>
        /// <param name="icon">
        /// The icon.
        /// </param>
        public void ChangeTrayIcon(ApplicationIconType icon)
        {
            Uri uri = new Uri(
                "/PresentationAid;component/Resources/Icons/presentation-aid-icon.ico", UriKind.RelativeOrAbsolute);

            switch (icon)
            {
                case ApplicationIconType.Ready:
                    uri = new Uri(
                        "/PresentationAid;component/Resources/Icons/presentation-aid-ready-icon.ico", 
                        UriKind.RelativeOrAbsolute);

                    break;
                case ApplicationIconType.Warning:
                    uri = new Uri(
                        "/PresentationAid;component/Resources/Icons/presentation-aid-icon-warn.ico", 
                        UriKind.RelativeOrAbsolute);

                    break;
                case ApplicationIconType.Error:
                    uri = new Uri(
                        "/PresentationAid;component/Resources/Icons/presentation-aid-disconnected-icon.ico", 
                        UriKind.RelativeOrAbsolute);

                    break;
            }

            StreamResourceInfo streamInfo = Application.GetResourceStream(uri);

            if (streamInfo != null)
            {
                this.applicationIconType = icon;
                this.NotifyIcon.Icon = new Icon(streamInfo.Stream);
            }
        }

        /// <summary>
        /// Closes gesture window
        /// </summary>
        public void CloseGestureWindow()
        {
            Logger.Info("Method: CloseGestureWindow");

            this.gestureDialog.Hide();

            // Reassign main window's gesture recognized event again
            Logger.Trace("Method: CloseGestureWindow - AddGestureRecognizedEvent");

            KinectSensorManager.Instance.GestureRecognized += this.OnGestureRecognized;
        }

        /// <summary>
        /// Displays gesture dialog
        /// </summary>
        public void DisplayGestureWindow()
        {
            Logger.Info("Method: DisplayGestureWindow");

            this.gestureDialog.Show();

            // When we activate gesture dialog, we must make sure that commands are not executed,
            // notifications not shown and similar. So we need to remove the mainwindow's gesture recognized event.
            Logger.Trace("Method: DisplayGestureWindow - RemoveGestureRecognizedEvent");

            KinectSensorManager.Instance.GestureRecognized -= this.OnGestureRecognized;
        }

        /// <summary>
        /// Displays default notification warning
        /// </summary>
        /// <param name="title">
        /// Notification title
        /// </param>
        /// <param name="text">
        /// Notification text
        /// </param>
        public void DisplayNotification(string title, string text)
        {
            this.DisplayNotification("Images/Icons/warning_32.png", title, text);
        }

        /// <summary>
        /// Displays custom notification balloon
        /// </summary>
        /// <param name="uri">
        /// Uri to image
        /// </param>
        /// <param name="title">
        /// Notification title
        /// </param>
        /// <param name="text">
        /// Notification text
        /// </param>
        /// <param name="delay">
        /// Delay timer
        /// </param>
        public void DisplayNotification(string uri, string title, string text, int delay = 5000)
        {
            if (!SettingManager.Instance.DisplayPopupNotifications)
            {
                return;
            }

            Logger.Debug(
                "Method: DisplayNotification - Uri: {0}, Title: {1}, Text: {2}, Delay: {3}", uri, title, text, delay);

            NotificationControl notification = new NotificationControl
                                                   {
                                                       NotificationImage = uri, 
                                                       NotificationTitle = title, 
                                                       NotificationText = text, 
                                                       CloseDelay = delay
                                                   };

            if (delay > 0)
            {
                this.NotifyIcon.ShowCustomBalloon(notification, PopupAnimation.Fade, delay);
            }
            else
            {
                this.NotifyIcon.ShowCustomBalloon(notification, PopupAnimation.Fade, null);
            }
        }

        /// <summary>
        /// Displays overlay window
        /// </summary>
        /// <param name="title">Overlay window title
        /// </param>
        /// <param name="text">Overlay window text
        /// </param>
        public void DisplayOverlayWindow(string title, string text)
        {
            this.DisplayOverlayWindow(null, title, text);
        }

        /// <summary>
        /// Displays overlay window with image and delay in milliseconds
        /// </summary>
        /// <param name="image">URI to image displayed on window
        /// </param>
        /// <param name="title">Overlay window title
        /// </param>
        /// <param name="text">Overlay window text
        /// </param>
        /// <param name="closeDelay">Delay to close window
        /// </param>
        public void DisplayOverlayWindow(string image, string title, string text, int closeDelay = 0)
        {
            if (!SettingManager.Instance.DisplayOverlay)
            {
                // Show a popup instead of display overlay, only if we do not have it opened yet
                if ((image != null) && image.EndsWith("presenter.png") && (this.NotifyIcon.CustomBalloon == null))
                {
                    this.DisplayNotification("Images/Icons/user_32.png", title, text, 0);
                }
                else
                {
                    this.DisplayNotification(image, title, text);
                }

                return;
            }

            Logger.Debug(
                "Method: DisplayOverlayWindow - Image: {0}, Title: {1}, Text: {2}, Debug: {3}", 
                image, 
                title, 
                text, 
                closeDelay);

            this.overlayWindow.OverlayImage = image;
            this.overlayWindow.OverlayText = text;
            this.overlayWindow.OverlayTitle = title;

            if (closeDelay == 0)
            {
                this.overlayWindow.HasNoDelay = true;
            }
            else
            {
                this.overlayWindow.CloseDelay = closeDelay;
                this.overlayWindow.HasNoDelay = false;
            }

            this.overlayWindow.Show();
        }

        /// <summary>
        /// Forces to close notification window
        /// </summary>
        public void ForceCloseNotificationWindow()
        {
            if (SettingManager.Instance.DisplayPopupNotifications && (this.NotifyIcon.CustomBalloon != null))
            {
                NotificationControl popup = (NotificationControl)this.NotifyIcon.CustomBalloon.Child;

                if (popup.CloseDelay == 0)
                {
                    Logger.Debug("Method: ForceCloseNotificationWindow");

                    this.NotifyIcon.CloseBalloon();
                }
            }
        }

        /// <summary>
        /// Closes overlay window by force
        /// </summary>
        public void ForceCloseOverlayWindow()
        {
            // If we do not display overlay, we probably displayed notification, so close it
            if (!SettingManager.Instance.DisplayOverlay)
            {
                this.ForceCloseNotificationWindow();

                return;
            }

            if (this.overlayWindow.IsVisible && this.overlayWindow.HasNoDelay)
            {
                Logger.Debug("Method: ForceCloseOverlayWindow");

                this.overlayWindow.Hide();
            }
        }

        /// <summary>
        /// Simple gesture recognized event sent to gesture engine
        /// </summary>
        /// <param name="sender">Sender of the recognized gesture
        /// </param>
        /// <param name="e">Gesture event argument
        /// </param>
        public void OnGestureRecognized(object sender, GestureEventArgs e)
        {
            Logger.Info(
                "Event: GestureRecognized - GestureCommand: {0}, TrackingId: {1}, ControlId: {2}, ControlGesture: {3}", 
                e.Command.ToString(), 
                e.TrackingId, 
                KinectSensorManager.Instance.GestureEngine.ControlId, 
                KinectSensorManager.Instance.GestureEngine.ControlGesture.ToString());

            // Keep all the UI stuff here, so we open notifications from here
            string notificationTitle = string.Empty;
            string notificationText = string.Empty;

            string iconUrl = "Images/Icons/warning_32.png";

            // Updated logic, gets correctly mapped command from GestureEngine, because the configurable
            // commands were added later and this presented an error.

            // First need to check which gesture engine are we working with

            // Get SlideShowCommand Mapping
            SlideShowCommand command = KinectSensorManager.Instance.GestureEngine.GetSlideShowCommand(e.Command);

            Logger.Debug(
                "EventDetail: GestureRecognized - MappedSlideShowCommand: {0}, IsInSlideshow: {1}", 
                command.ToString(), 
                KinectSensorManager.Instance.GestureEngine.IsInSlideshow);

            // Control gesture was performed and the presenter is not in control, so he is given control
            if ((e.Command == KinectSensorManager.Instance.GestureEngine.ControlGesture)
                && !KinectSensorManager.Instance.GestureEngine.IsInControl(e.TrackingId)
                && KinectSensorManager.Instance.GestureEngine.ControlGesture != GestureCommand.None)
            {
                notificationTitle = "Person: " + e.TrackingId + " is now presenting";
                notificationText =
                    "You are now in control of the presentation, you may use gestures to control presentation.";
                iconUrl = "Images/Icons/user_32.png";
            }
            else if (KinectSensorManager.Instance.GestureEngine.IsInControl(e.TrackingId)) 
            {
                // Person is in control, control presentation
                switch (command)
                {
                    case SlideShowCommand.StartStopSlideshow:
                        if (KinectSensorManager.Instance.GestureEngine.IsInSlideshow)
                        {
                            notificationTitle = "Ending Slideshow";
                            notificationText =
                                "Slideshow finished, returning to PowerPoint. Thank you for using PresentationAid!";
                            iconUrl = "Images/Icons/exit_32.png";
                        }
                        else
                        {
                            notificationTitle = "Starting Slideshow";
                            notificationText = "Starting Slideshow of the presentation. Good luck to all of you!";
                            iconUrl = "Images/Icons/presentation_32.png";
                        }

                        break;
                    case SlideShowCommand.NextSlide:
                        if (KinectSensorManager.Instance.GestureEngine.GetType() != typeof(PowerPointEngine)
                            || KinectSensorManager.Instance.GestureEngine.IsInSlideshow)
                        {
                            notificationTitle = "Next slide";
                            notificationText = "Moving to the next slide of the presentation.";
                            iconUrl = "Images/Icons/next_32.png";
                        }

                        break;
                    case SlideShowCommand.PreviousSlide:
                        if (KinectSensorManager.Instance.GestureEngine.GetType() != typeof(PowerPointEngine)
                            || KinectSensorManager.Instance.GestureEngine.IsInSlideshow)
                        {
                            notificationTitle = "Previous slide";
                            notificationText = "Moving to the next slide of the presentation.";
                            iconUrl = "Images/Icons/previous_32.png";
                        }

                        break;
                    default:
                        if (KinectSensorManager.Instance.GestureEngine.ControlGesture != e.Command)
                        {
                            notificationTitle = "Gesture detection warning";
                            notificationText =
                                "A gesture was detected by the system, but it is not mapped to a slideshow action. It is still exectued.";
                            iconUrl = "Images/Icons/warning2_32.png";
                        }

                        break;
                }
            }
            else
            {
                // Person is not in control, gesture ignored
                Logger.Debug(
                    "EventDetail: GestureRecognized - GestureIgnored, Gesture: {0}, TrackingId: {1}, ControlId: {2}, MappedSlideShowCommand: {3}", 
                    e.Command.ToString(), 
                    e.TrackingId, 
                    KinectSensorManager.Instance.GestureEngine.ControlId, 
                    command.ToString());

                this.DisplayNotTrackedNotice();
            }

            if (!string.IsNullOrEmpty(notificationTitle))
            {
                Logger.Debug(
                    "EventDetail: GestureRecognized - ExecuteGesture, Gesture: {0}, TrackingId: {1}, ControlId: {2}, MappedSlideShowCommand: {3}", 
                    e.Command.ToString(), 
                    e.TrackingId, 
                    KinectSensorManager.Instance.GestureEngine.ControlId, 
                    command.ToString());

                this.DisplayNotification(iconUrl, notificationTitle, notificationText);
                KinectSensorManager.Instance.GestureEngine.ExecuteGesture(e.Command, e.TrackingId);
            }
        }

        /// <summary>
        /// Toggles debug mode
        /// </summary>
        /// <param name="on">Debug mode is toggled on if true, default: true
        /// </param>
        public void ToggleDebugMode(bool on = true)
        {
            Logger.Info("Method: ToggleDebugMode - On: {0}", on);

            this.DebugTab.Visibility = !on ? Visibility.Collapsed : Visibility.Visible;

            // Remove/Add DebugTab Logger to increase performance
            if (SettingManager.Instance.DebugMode)
            {
                AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper
                                                      {
                                                          Name = "windowLogger", 
                                                          WrappedTarget = CustomLoggerTarget.Instance, 
                                                      };

                CustomLoggerTarget.Instance.Rule = new LoggingRule("*", LogLevel.Info, asyncWrapper);

                LogManager.Configuration.AddTarget("debugTab", asyncWrapper);
                LogManager.Configuration.LoggingRules.Add(CustomLoggerTarget.Instance.Rule);
                LogManager.Configuration.Reload();
            }
            else
            {
                LogManager.Configuration.LoggingRules.Remove(CustomLoggerTarget.Instance.Rule);
                LogManager.Configuration.RemoveTarget("debugTab");
                LogManager.Configuration.Reload();
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The about tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void AboutTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: AboutTrayMenuItemClick");

            About about = new About { Owner = this };
            about.ShowDialog();
        }

        /// <summary>
        /// Displays not tracked notice to user being an idiot or trying to confuse presenter. :)
        /// </summary>
        private void DisplayNotTrackedNotice()
        {
            Logger.Debug("Method: DisplayNotTrackedNotice, NotTrackedNoticeCount: {0}", this.notTrackedNoticeCount);

            if ((this.notTrackedNoticeCount > 5) && ((DateTime.Now - this.notTrackedFirstGesture).TotalSeconds < 30))
            {
                this.DisplayOverlayWindow(
                    "Images/Other/troll.png", 
                    "You are an idiot !", 
                    "You should know not to mess with your friend's presentation! If you want to take control, you should use the appropriate gesture. Otherwise just sit down and be quiet, so presenter can do his job properly.", 
                    4000);

                this.notTrackedNoticeCount = 0;
            }
            else
            {
                this.notTrackedNoticeCount++;
            }

            // Remember the time of first gesture
            if (this.notTrackedNoticeCount == 1)
            {
                this.notTrackedFirstGesture = DateTime.Now;
            }
        }

        /// <summary>
        /// The help tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void HelpTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: HelpTrayMenuItemClick");

            Process.Start("http://presentationaid.codeplex.com/documentation");
        }

        /// <summary>
        /// The kinect tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void KinectTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: KinectTrayMenuItemClick - IsVisible: {0}", this.IsVisible);

            if (!this.IsVisible)
            {
                this.Show();
            }

            this.MainTabControl.SelectedIndex = 1;
        }

        /// <summary>
        /// The notify icon tray mouse double click.
        /// </summary>
        /// <param name="sender">
        /// Sender of notify icon tray click
        /// </param>
        /// <param name="e">
        /// Event arguments
        /// </param>
        private void NotifyIconTrayMouseDoubleClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: NotifyIconTrayMouseDoubleClick - IsVisible: {0}", this.IsVisible);

            if (!this.IsVisible)
            {
                this.Show();
            }
        }

        /// <summary>
        /// EventHandler handles notifications and overlay windows
        /// </summary>
        /// <param name="sender">Sender of the event
        /// </param>
        /// <param name="args">Skeleton event arguments
        /// </param>
        private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs args)
        {
            using (SkeletonFrame frame = args.OpenSkeletonFrame())
            {
                if (frame == null)
                {
                    return;
                }

                frame.GetSkeletons(ref this.skeletons);

                // If slideshow is in action, we display an overlay message if there are no tracking skeletons in scene
                if (this.skeletons.All(s => s.TrackingState == SkeletonTrackingState.NotTracked))
                {
                    // Display overlay window if we are in slideshow to let presenter know they are not visible
                    if (KinectSensorManager.Instance.GestureEngine.IsInSlideshow
                        && SettingManager.Instance.NoPresenterOverlay)
                    {
                        this.DisplayOverlayWindow(
                            "Images/Other/presenter.png", 
                            "No presenter detected", 
                            "Sensor is currently not detecting any presenter in the scene. Reconfigure sensor to be able to see the presenter or walk in the scene.");
                    }
                }
                else if (this.skeletons.Any(s => s.TrackingState == SkeletonTrackingState.Tracked))
                {
                    // We search a tracking presenter, so we check if he is the only one and give him control

                    // Close overlay window incase it is open!
                    if (KinectSensorManager.Instance.GestureEngine.IsInSlideshow)
                    {
                        this.ForceCloseOverlayWindow();
                    }
                }
            }
        }

        /// <summary>
        /// The on update check finished.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="args">
        /// The args.
        /// </param>
        private void OnUpdateCheckFinished(object sender, OperationEventArgs args)
        {
            // If settings are available and updates are available, display notification
            Logger.Debug(
                "Event: UpdateCheckFinished - SelectedIndex: {0}, AvailableVersionCount: {1}", 
                this.MainTabControl.SelectedIndex, 
                args.UpdateInfo.AvailableVersions.Count);

            if ((this.MainTabControl.SelectedIndex != 2) && (args.UpdateInfo.AvailableVersions.Count > 0))
            {
                this.DisplayNotification(
                    "Images/Icons/info_32.png", 
                    "Update available!", 
                    "Select the settings tab and click UPDATE NOW button.");
            }
        }

        /// <summary>
        /// The presentation tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void PresentationTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: PresentationTrayMenuItemClick - IsVisible: {0}", this.IsVisible);

            if (!this.IsVisible)
            {
                this.Show();
            }

            this.MainTabControl.SelectedIndex = 0;
        }

        /// <summary>
        /// The quit tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void QuitTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: QuitTrayMenuItemClick");

            KinectSensorManager.Instance.CloseKinect();

            Logger.Trace("EventDetail: QuitTrayMenuItemClick - DisposeIcon");

            this.NotifyIcon.Dispose();

            Application.Current.Shutdown();
        }

        /// <summary>
        /// The settings tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void SettingsTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: SettingsTrayMenuItemClick - IsVisible: {0}", this.IsVisible);

            if (!this.IsVisible)
            {
                this.Show();
            }

            this.MainTabControl.SelectedIndex = 2;
        }

        /// <summary>
        /// Updates tray icon based on presentation tab
        /// </summary>
        /// <param name="sender">
        /// Sender of the update event
        /// </param>
        /// <param name="e">
        /// Event arguments
        /// </param>
        private void Update(object sender, EventArgs e)
        {
            string[] status = new string[3];

            status[0] = this.PresentationTabElement.GetStepSetting(1);
            status[1] = this.PresentationTabElement.GetStepSetting(2);
            status[2] = this.PresentationTabElement.GetStepSetting(3);

            if (status.Any(s => s == "error"))
            {
                if (this.applicationIconType != ApplicationIconType.Error)
                {
                    Logger.Trace("Method: Update - TrayIconToError");

                    this.ChangeTrayIcon(ApplicationIconType.Error);

                    this.TrayMenuStatus.Header = "Error in configuration...";
                    this.NotifyIcon.ToolTipText = "PresentationAid - Error";
                }

                // Reset move to tray
                this.hasMovedToTray = false;
            }
            else if (status.Any(s => s == "warning2"))
            {
                if (this.applicationIconType != ApplicationIconType.Warning)
                {
                    Logger.Trace("Method: Update - TrayIconToWarning");

                    this.ChangeTrayIcon(ApplicationIconType.Warning);

                    this.TrayMenuStatus.Header = "Check configuration...";
                    this.NotifyIcon.ToolTipText = "PresentationAid - Warning";
                }

                // Reset move to tray
                this.hasMovedToTray = false;
            }
            else if (status.All(s => s == "check"))
            {
                if (this.applicationIconType != ApplicationIconType.Ready)
                {
                    Logger.Trace("Method: Update - TrayIconToReady");

                    this.ChangeTrayIcon(ApplicationIconType.Ready);

                    this.TrayMenuStatus.Header = "Ready to start...";
                    this.NotifyIcon.ToolTipText = "PresentationAid - Ready";
                }

                // Moving to tray now
                if (SettingManager.Instance.CanMinimizeToTray && SettingManager.Instance.MoveToTray
                    && !this.hasMovedToTray)
                {
                    if (this.IsVisible)
                    {
                        Logger.Debug(
                            "Method: Update - MoveToTray, CanMinimizeToTray: {0}, MoveToTray: {1}, HasMovedToTray: {2}", 
                            SettingManager.Instance.CanMinimizeToTray, 
                            SettingManager.Instance.MoveToTray, 
                            this.hasMovedToTray);

                        this.Hide();

                        this.hasMovedToTray = true;
                    }
                }
            }
        }

        /// <summary>
        /// The website tray menu item click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void WebsiteTrayMenuItemClick(object sender, RoutedEventArgs e)
        {
            Logger.Debug("Event: WebsiteTrayMenuItemClick");

            Process.Start("http://presentationaid.codeplex.com/");
        }

        /// <summary>
        /// Window is closed, need to clean either minimize it to tray or close it
        /// </summary>
        /// <param name="sender">
        /// Sender of the event
        /// </param>
        /// <param name="e">
        /// Event arguments
        /// </param>
        private void WindowClosing(object sender, CancelEventArgs e)
        {
            Logger.Debug("Event: WindowClosing - CanMinimizeToTray: {0}", SettingManager.Instance.CanMinimizeToTray);

            if (SettingManager.Instance.CanMinimizeToTray)
            {
                e.Cancel = true;
                this.Hide();
            }
            else
            {
                KinectSensorManager.Instance.CloseKinect();

                this.NotifyIcon.Dispose();

                Application.Current.Shutdown();
            }
        }

        #endregion
    }
}